from PySide6 import QtWidgets, QtCore
from PySide6.QtWidgets import QMainWindow, QComboBox, QLineEdit
from FluidClass.FluidSettings import FluidSettings as Fluid
from user_interface.ui_main import Ui_MainWindow
from user_interface.ui_fluid_settings import Ui_Dialog as Ui_Dialog_fluid
from WidgetElementsParams.ChooseElementWidget import WindowElemParams
from FluidClass.FluidSettings import FluidSettings
from database.DataBaseApp import CurrentSessionHydraulicLine as hydraulic_line
from HandlerButtons.HandlerDeleteButton import HandlerDeleteButton
from HandlerButtons.HandlerInsertButton import HandlerInsertButton
from user_interface.render_window import render_window_edit_elem, render_window_errors, render_window_fluid_settings
from HandlerButtons.HandlerAddButton import HandlerAddButton
from HandlerButtons.HandlerEditFluidButton import (edit_fluid as edit_f,
                                                   view_fluid_data as view_fd,
                                                   except_fluid_data as except_fd,
                                                   raise_exception)
import styles.styles_elements as styles
import copy


class PressureFall(QMainWindow):
    def __init__(self):
        super(PressureFall, self).__init__()

        self.current_elem_settings = None
        self.unit = 'Па'
        self.ui_window_elem = None
        self.indx_edit = None
        self.total_pressure_drop = 0
        self.total_coeff_resist = 0
        self.params_elem_data = None
        self.instance_elem = None
        self.work_fluid = FluidSettings()
        self.current_elem_resistance = None
        self.indx_insert = ''
        self.data_fluid = {}

        self.hydraulic_line = hydraulic_line()
        self.elem_index = 0

        self.ui = Ui_MainWindow()

        self.ui.setupUi(self)

        self.ui_table = self.ui.table_elements_line

        self.ui.btn_edit_fluid_settings.clicked.connect(self.open_edit_fluid_window)
        self.ui.btn_add_element.clicked.connect(self.open_add_element_window)
        self.ui.btn_del_element.clicked.connect(self.delete_element)
        self.ui.btn_edit_element.clicked.connect(self.open_edit_element_window)
        self.ui.comboBox.currentIndexChanged.connect(self.unit_main_window)
        self.exception_handler = HandlerAddButton()

    def unit_main_window(self):
        self.unit = self.ui.comboBox.currentText()
        self.view_total_pressure_drop()

    def open_edit_fluid_window(self):

        self.fluid_settings_window = QtWidgets.QDialog()
        self.ui_window_fluid = Ui_Dialog_fluid()
        self.ui_window_fluid.setupUi(self.fluid_settings_window)
        render_window_fluid_settings(self.ui, self.ui_window_fluid)
        self.fluid_settings_window.show()

        self.ui_window_fluid.btn_save_fluid.clicked.connect(self.edit_fluid)
        if len(self.hydraulic_line.hydraulic_line) > 0:
            self.ui_window_fluid.btn_save_fluid.clicked.connect(self.update_table_change_fluid)
        self.ui_window_fluid.btn_save_fluid.clicked.connect(self.view_fluid_data)
        self.ui_window_fluid.btn_save_fluid.clicked.connect(self.view_total_pressure_drop)
        self.ui_window_fluid.btn_save_fluid.clicked.connect(self.fluid_settings_window.close)

    def edit_fluid(self):
        current_fluid_settings = edit_f(self.ui_window_fluid)
        list_errors_string = except_fd(current_fluid_settings, self.ui_window_fluid)
        try:
            raise_exception(list_errors_string)
        except ValueError:
            self.open_edit_fluid_window()
            for name_property_fluid in self.ui_window_fluid.get_name_property_fluid():
                if name_property_fluid.objectName() in list_errors_string:
                    name_property_fluid.setStyleSheet(styles.QLineEdit_Error)
                    name_property_fluid.setText('Некорректное значение')
                else:
                    name_property_fluid.setText(current_fluid_settings[name_property_fluid.objectName()])
        else:
            self.data_fluid = edit_f(self.ui_window_fluid)
            self.work_fluid = Fluid(self.data_fluid)

    def view_fluid_data(self):
        view_fd(self.ui, self.data_fluid)

    def open_add_element_window(self):
        self.ui_window_elem = WindowElemParams()
        self.indx_insert = self.ui.IndexAdd.text()
        sender = self.sender()
        if sender is None and self.indx_insert == '':
            self.ui_window_elem = render_window_errors(WindowElemParams(), self.current_elem_settings)
            self.ui_window_elem.show()
            self.ui_window_elem.btn_save_element.clicked.connect(self.add_new_element)
            self.ui_window_elem.btn_save_element.clicked.connect(self.view_table_element_data)
            self.ui_window_elem.btn_save_element.clicked.connect(self.view_total_pressure_drop)
            self.ui_window_elem.btn_save_element.clicked.connect(self.ui_window_elem.close)
        elif sender is None and self.indx_insert:
            self.ui_window_elem = render_window_errors(WindowElemParams(), self.current_elem_settings)
            self.ui_window_elem.show()
            self.ui_window_elem.btn_save_element.clicked.connect(self.add_new_element)
            self.ui_window_elem.btn_save_element.clicked.connect(self.insert_elem)
            self.ui_window_elem.btn_save_element.clicked.connect(self.update_table_element_after_delete_insert)
            self.ui_window_elem.btn_save_element.clicked.connect(self.view_total_pressure_drop)
            self.ui_window_elem.btn_save_element.clicked.connect(self.ui_window_elem.close)

        elif sender.text() == 'Добавить элемент' and self.indx_insert == '':
            self.ui_window_elem.show()
            self.ui.IndexAdd.setStyleSheet(styles.QLineIndex_StyleSheet)
            self.ui_window_elem.btn_save_element.clicked.connect(self.add_new_element)
            self.ui_window_elem.btn_save_element.clicked.connect(self.view_table_element_data)
            self.ui_window_elem.btn_save_element.clicked.connect(self.view_total_pressure_drop)
            self.ui_window_elem.btn_save_element.clicked.connect(self.ui_window_elem.close)

        elif sender.text() == 'Добавить элемент' and self.indx_insert:
            try:
                self.hydraulic_line.hydraulic_line[self.indx_insert]

            except KeyError:
                self.ui.IndexAdd.clear()
                self.ui.IndexAdd.setStyleSheet(styles.QLineIndex_Error)
            else:
                self.ui_window_elem.show()
                self.ui.IndexAdd.setStyleSheet(styles.QLineIndex_StyleSheet)
                self.ui_window_elem.btn_save_element.clicked.connect(self.add_new_element)
                self.ui_window_elem.btn_save_element.clicked.connect(self.insert_elem)
                self.ui_window_elem.btn_save_element.clicked.connect(self.update_table_element_after_delete_insert)
                self.ui_window_elem.btn_save_element.clicked.connect(self.view_total_pressure_drop)
                self.ui_window_elem.btn_save_element.clicked.connect(self.ui_window_elem.close)

    def open_edit_element_window(self):
        self.indx_edit = self.ui.IndexAdd_2.text()
        sender = self.sender()
        if sender.text() == 'Редактировать элемент':
            try:
                self.hydraulic_line.hydraulic_line[self.indx_edit]
            except KeyError:
                self.ui.IndexAdd_2.clear()
                self.ui.IndexAdd_2.setStyleSheet(styles.QLineIndex_Error)
            else:
                self.ui_window_elem = render_window_edit_elem(self,
                                                              WindowElemParams(),
                                                              self.indx_edit,
                                                              )
                self.current_elem_settings = self.exception_handler.get_dict_params_widget(self.ui_window_elem)
                self.ui_window_elem = render_window_errors(WindowElemParams(), self.current_elem_settings)
                self.ui_window_elem.show()
                self.ui.IndexAdd_2.setStyleSheet(styles.QLineIndex_StyleSheet)
                self.ui_window_elem.btn_save_element.clicked.connect(self.edit_element)

                self.ui_window_elem.btn_save_element.clicked.connect(self.update_table_element_after_delete_insert)
                self.ui_window_elem.btn_save_element.clicked.connect(self.view_total_pressure_drop)
                self.ui_window_elem.btn_save_element.clicked.connect(self.ui_window_elem.close)
        else:
            self.current_elem_settings = self.exception_handler.get_dict_params_widget(self.ui_window_elem)
            self.ui_window_elem = render_window_errors(WindowElemParams(), self.current_elem_settings)
            self.ui_window_elem.show()

            self.ui.IndexAdd_2.setStyleSheet(styles.QLineIndex_StyleSheet)
            self.ui_window_elem.btn_save_element.clicked.connect(self.edit_element)

            self.ui_window_elem.btn_save_element.clicked.connect(self.update_table_element_after_delete_insert)
            self.ui_window_elem.btn_save_element.clicked.connect(self.view_total_pressure_drop)
            self.ui_window_elem.btn_save_element.clicked.connect(self.ui_window_elem.close)

    def delete_element(self):
        indx_del = self.ui.IndexAdd_3.text()
        sender = self.sender()
        if sender.text() == 'Удалить элемент' and indx_del:
            try:
                self.hydraulic_line.hydraulic_line[indx_del]
            except KeyError:
                self.ui.IndexAdd_3.clear()
                self.ui.IndexAdd_3.setStyleSheet(styles.QLineIndex_Error)
            else:
                self.hydraulic_line.hydraulic_line = HandlerDeleteButton.delete_elem(self.hydraulic_line.hydraulic_line,
                                                                                     int(indx_del))
                self.ui_table.removeRow(int(indx_del) - 1)
                self.update_table_element_after_delete_insert()
                self.view_total_pressure_drop()
                self.ui.IndexAdd_3.setStyleSheet(styles.QLineIndex_StyleSheet)
        else:
            self.ui.IndexAdd_3.setStyleSheet(styles.QLineIndex_Error)

    def edit_element(self):
        self.elem_index = self.indx_edit
        self.current_elem_settings = self.exception_handler.get_dict_params_widget(self.ui_window_elem)
        list_errors_string = self.exception_handler.exception_element(self.ui_window_elem)
        try:
            self.exception_handler.raise_exception(list_errors_string)
        except ValueError:
            self.open_edit_element_window()
            for name_property_elem in self.ui_window_elem.get_params_current_widget():
                if name_property_elem.objectName() in list_errors_string:
                    if isinstance(name_property_elem, QComboBox):
                        name_property_elem.setStyleSheet(styles.QComboBox_Error)
                    else:
                        name_property_elem.setStyleSheet(styles.QLineEdit_Error)
                        name_property_elem.setText(list_errors_string[name_property_elem.objectName()])
        else:
            self.instance_elem = self.exception_handler.add_or_edit_elem(self.ui_window_elem, self.work_fluid)
            self.instance_elem.index = str(self.indx_edit)
            self.hydraulic_line.edit_element(self.instance_elem)

    def add_new_element(self):
        self.elem_index = len(self.hydraulic_line.hydraulic_line) + 1
        self.current_elem_settings = self.exception_handler.get_dict_params_widget(self.ui_window_elem)
        list_errors_string = self.exception_handler.exception_element(self.ui_window_elem)
        try:
            self.exception_handler.raise_exception(list_errors_string)
        except ValueError:
            self.open_add_element_window()
            for name_property_elem in self.ui_window_elem.get_params_current_widget():
                if name_property_elem.objectName() in list_errors_string:
                    if isinstance(name_property_elem, QComboBox):
                        name_property_elem.setStyleSheet(styles.QComboBox_Error)
                    else:
                        name_property_elem.setStyleSheet(styles.QLineEdit_Error)
                        name_property_elem.setText(list_errors_string[name_property_elem.objectName()])
        else:
            self.instance_elem = self.exception_handler.add_or_edit_elem(self.ui_window_elem, self.work_fluid)
            self.instance_elem.index = str(self.elem_index)
            if self.indx_insert == '':
                self.hydraulic_line.add_element(self.instance_elem)

    def insert_elem(self):

        self.hydraulic_line.hydraulic_line = HandlerInsertButton.insert_elem_above(
            self.hydraulic_line.hydraulic_line,
            self.indx_insert,
            self.instance_elem,
        )
        self.indx_insert = ''

    def view_table_element_data(self):
        view_elem_data = self.instance_elem.get_params_element()
        self.ui_table.insertRow(self.ui_table.rowCount())

        for name_parameter_elem, number_col in zip(view_elem_data, range(0, 8)):

            if name_parameter_elem == 'params_geom':
                params_elem = '\n'.join([f'{k}: {str(v)}' for k, v in view_elem_data['params_geom'].items()])
                item = QtWidgets.QTableWidgetItem(params_elem)
            else:
                item = QtWidgets.QTableWidgetItem(str(view_elem_data[name_parameter_elem]))
            item.setTextAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter)
            self.ui_table.resizeRowsToContents()
            row = int(self.instance_elem.index) - 1
            self.ui_table.setItem(row, number_col, item)

    def update_table_change_fluid(self):
        row = 0
        for elem in self.hydraulic_line.hydraulic_line.values():
            elem.fluid = self.work_fluid
            view_elem_data = tuple(elem.get_params_element().values())[4:]
            for parameter_elem, number_col in zip(view_elem_data, range(4, 8)):
                item = QtWidgets.QTableWidgetItem(str(parameter_elem))
                item.setTextAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter)
                self.ui_table.setItem(row, number_col, item)
            row += 1

    def update_table_element_after_delete_insert(self):
        row = 0
        for elem in self.hydraulic_line.hydraulic_line.values():
            self.ui_table.removeRow(row)
            self.ui_table.insertRow(row)
            view_elem_data = elem.get_params_element()
            for parameter_elem, number_col in zip(view_elem_data, range(0, 8)):

                if parameter_elem == 'params_geom':
                    params_elem = '\n'.join([f'{k}: {str(v)}' for k, v in view_elem_data['params_geom'].items()])
                    item = QtWidgets.QTableWidgetItem(params_elem)
                else:
                    item = QtWidgets.QTableWidgetItem(str(view_elem_data[parameter_elem]))

                item.setTextAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter)
                self.ui_table.resizeRowsToContents()
                self.ui_table.setItem(row, number_col, item)
            row += 1

    def view_total_pressure_drop(self):
        self.total_pressure_drop = self.hydraulic_line.update_total_pressure_drop(self.unit)
        self.total_coeff_resist = self.hydraulic_line.update_total_resistance_coefficient()
        self.ui.value_pressure.setText(str(self.total_pressure_drop))
        self.ui.value_coeff.setText(str(self.total_coeff_resist))
        self.instance_elem = None
